package com.grizz.snake.controller;

import java.awt.Dimension;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Vector2f;

import com.grizz.snake.Game;
import com.grizz.snake.controller.factory.EntityFactory;
import com.grizz.snake.map.Map;
import com.grizz.snake.player.Snake;
import com.grizz.snake.target.Food;

public class Mediator {
	private Snake snake;
	private Map map;
	private MovementService movementService;
	private InputController inputController;
	private Game game;
	private EntityFactory entityFactory;
	private Food food;
	
	//### Registers
	public void register(Snake snake){
		this.snake = snake;
	}

	public void register(Map map) {
		this.map = map;
	}

	public void register(MovementService movementService) {
		this.movementService = movementService;
	}

	public void register(InputController inputController) {
		this.inputController = inputController;
	}

	public void register(Game game) {
		this.game = game;
	}

	public void register(EntityFactory entityFactory) {
		this.entityFactory = entityFactory;
	}

	public void register(Food food) {
		this.food = food;
	}
	//### End of registers

	public boolean isPaused() {
		return game.isPaused();
	}

	public void setPause(boolean isPaused) {
		game.setPause(isPaused);
	}
	
	public void resetGameState() throws SlickException{
		game.startGame();
		snake = entityFactory.getSnake();
		food = entityFactory.getFood();
		inputController.reset();
		food.reset();
	}

	public boolean checkCollision(Vector2f p) {
		return !map.isWalkable(p);
	}

	public void feedSnake() {
		snake.eat();
	}

	public void snakeDied() {
		game.gameOver();
	}
	
	public void moveSnake() {
		int directionKey = inputController.getLastDirectionKeyPressed();
		moveSnake(directionKey);
		if(food.checkCollision(snake.getLocation())){
			feedSnake();
			food.reset();
		}
	}
	
	private void moveSnake(int directionKey){
		switch(directionKey){
			case Input.KEY_LEFT : snake.move(Snake.GO_LEFT); break;
			case Input.KEY_RIGHT : snake.move(Snake.GO_RIGHT); break;
			case Input.KEY_UP : snake.move(Snake.GO_UP); break;
			case Input.KEY_DOWN : snake.move(Snake.GO_DOWN); break;
		}
	}

	public void drawMap() {
		map.render();
	}

	public void drawSnake() {
		snake.render();
	}
	
	public void drawFood() {
		food.render();
	}

	public void update(GameContainer container, int delta) throws SlickException {
		inputController.update(container.getInput());
		if(!game.isPaused())
			movementService.update(delta);
	}

	public Dimension getMapTileDimension() {
		return map.getTilesDimension();
	}

	public Dimension getMapDimension() {
		return map.getMapDimension();
	}

	public void setDelay(int movementDelayFast) {
		movementService.setDelay(movementDelayFast);
	}
}
